package com.start.security.details;

import com.start.common.constant.StartConstant;
import com.start.common.details.BaseUserDetails;
import com.start.common.entity.StartBaseUser;
import com.start.common.std.IStartUserType;
import com.start.common.tools.ClassTools;
import com.start.common.tools.SpringContextTools;
import com.start.security.configs.StartSecurityProperties;
import com.start.security.configs.StartSecurityUserProperties;
import com.start.security.configs.StartSuperAdminUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 基本用户Details
 */
public abstract class IStartBaseUserDetailsService implements UserDetailsService, IStartUserType {

    private static boolean LOAD_FLAG;
    private static StartSecurityUserProperties configuration;

    public StartSecurityUserProperties getConfiguration() {
        if (LOAD_FLAG) {
            return configuration;
        }
        LOAD_FLAG = true;
        if (configuration != null) return configuration;
        try {
            StartSecurityProperties bean = SpringContextTools.getBean(StartSecurityProperties.class);

            configuration = bean.getUser();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return configuration;
    }

    @Override
    public final UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        BaseUserDetails details = null;
        if (getConfiguration() != null && getConfiguration().getEnable()) {
            details = handlerSystemSuperAdmin(userName);
        }
        if (details != null) {
            return details;
        }
        return startLoadUserByUsername(userName);
    }

    /**
     * 加载用户信息
     *
     * @param userName
     * @return
     */
    public abstract BaseUserDetails startLoadUserByUsername(String userName);

    /**
     * 处理超级用户
     *
     * @param userName
     * @return
     */
    public BaseUserDetails handlerSystemSuperAdmin(String userName) {
        StartSecurityUserProperties adminUserConfiguration = getConfiguration();
        if (adminUserConfiguration.getUsers() == null || adminUserConfiguration.getUsers().isEmpty())
            return null;
        List<StartSuperAdminUser> collect = adminUserConfiguration.getUsers().stream().filter(e -> !StringUtils.isEmpty(e.getUserName()) && e.getUserName().equals(userName)).collect(Collectors.toList());
        if (collect.isEmpty()) return null;
        StartSuperAdminUser superAdminUser = collect.get(0);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        String date = simpleDateFormat.format(new Date());
        StartBaseUser sysUser = createSysUser(superAdminUser, date);
        if (sysUser == null) return null;
        BaseUserDetails baseUserDetails = new BaseUserDetails(sysUser);
        baseUserDetails.setSuperUser(true);
        baseUserDetails.setStartUserType(getStartUserType());
        return baseUserDetails;
    }

    private StartBaseUser createSysUser(StartSuperAdminUser user, String date) {
        if (StringUtils.isAllBlank(user.getClazz())) {
            return null;
        }
        StartBaseUser sysUser = (StartBaseUser) ClassTools.createObject(user.getClazz());
        if (sysUser == null) return null;
        sysUser.setId("s_" + user.getUserName());
        sysUser.setUserName(user.getUserName());
        sysUser.setIsEnabled(0);
        sysUser.setIsLocked(0);
        sysUser.setRealName(user.getUserName());
        sysUser.setNickName(user.getUserName());
        sysUser.setIsEnabled(1);
        sysUser.setIsLocked(0);
        String pwd = date;
        if (!StringUtils.isEmpty(user.getPassword())) pwd = user.getPassword() + pwd;
        String encode = StartConstant.passwordEncoder.encode(pwd);
        sysUser.setUserPwd(encode);
        return sysUser;
    }

    public String getStartUserType() {
        return StartConstant.ClientUserType.ADMIN_USER;
    }
}
